package com.ysy.logistics.asp;

/**
 * @ClassDescription:
 * @Author:姚斯羽
 * @Create:2025/3/21 15:18
 **/

import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson2.JSON;
import com.ysy.common.resp.ResultData;
import com.ysy.logistics.entities.oam.OperationLog;
import com.ysy.logistics.myannotation.OperateLog;
import com.ysy.logistics.service.oam.OperationLogService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.Objects;

/**
 * <p>
 * 操作日志、异常日志切面
 * </p>
 */
@Slf4j
@Aspect
@Component
public class LogAspect {

    @Resource
    OperationLogService operationLogService;

    @Pointcut("@annotation(com.ysy.logistics.myannotation.OperateLog)")//在注解的位置切入代码
    public void operLogPoinCut() {
    }


    @AfterReturning(value = "operLogPoinCut()", returning = "result")
    public void saveOperationLog(JoinPoint joinPoint, Object result) {
        log.info("切面日志：{}", result.toString());
        String succeed = "成功";
        try {
            //cop result
            if (result instanceof ResultData) {
                ResultData<Object> resultData = (ResultData<Object>) result;
                if (!resultData.successFlag()) {
                    succeed = "失败";
                }
            }
        } catch (Exception e) {
            log.info("切面异常：{},返回类不是ResultData，默认操作成功", e);
        }
        log.info("切面日志succeed：{}", succeed);
        try {
            // 从切面织入点处通过反射机制获取织入点处的方法
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            // 获取切入点所在的方法
            Method method = signature.getMethod();
            // 获取操作
            OperateLog operateLog = method.getAnnotation(OperateLog.class);
            if (Objects.nonNull(operateLog)) {
                // 将入参转换成json
                String params = argsArrayToString(joinPoint.getArgs());
                if (params.length() > 256) {
                    params = params.substring(0, 256);
                }
                OperationLog operationLog = new OperationLog();
                Object loginId = null;
                try {
                    loginId = StpUtil.getLoginId();
                } catch (Exception e1) {
                    log.info("获取登录用户失败：{}", e1);
                }
                operationLog = operationLog.setLogType("业务日志")
                        .setLogName(operateLog.value())
                        .setUserId(Objects.nonNull(loginId) ? loginId.toString() : "")
                        .setClassName(joinPoint.getSignature().getDeclaringTypeName())
                        .setMethod(joinPoint.getSignature().getName())
                        .setCreateTime(new Date())
                        .setSucceed(succeed)
                        .setMessage(params);
                operationLogService.add(operationLog);
            }

        } catch (Exception e) {
            log.info("切面异常：{}", e);
        }
    }



    @AfterThrowing(value = "operLogPoinCut()", throwing = "e")
    public void saveExceptionLog(JoinPoint joinPoint, Throwable e) {
        String succeed = "失败";
        try {
            // 从切面织入点处通过反射机制获取织入点处的方法
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            // 获取切入点所在的方法
            Method method = signature.getMethod();
            // 获取操作
            OperateLog operateLog = method.getAnnotation(OperateLog.class);
            if (Objects.nonNull(operateLog)) {
                // 将入参转换成json
                String params = argsArrayToString(joinPoint.getArgs());
                if (params.length() > 256) {
                    params = params.substring(0, 256);
                }
                OperationLog operationLog = new OperationLog();
                Object loginId = null;
                try {
                    loginId = StpUtil.getLoginId();
                } catch (Exception e1) {
                    log.info("获取登录用户失败：{}", e1);
                }
                operationLog = operationLog.setLogType("异常日志")
                        .setLogName(operateLog.value())
                        .setUserId(Objects.nonNull(loginId) ? loginId.toString() : "")
                        .setClassName(joinPoint.getSignature().getDeclaringTypeName())
                        .setMethod(joinPoint.getSignature().getName())
                        .setCreateTime(new Date())
                        .setSucceed(succeed)
                        .setMessage(e.getMessage() + "\n" + params);
                operationLogService.add(operationLog);
            }

        } catch (Exception e2) {
            log.info("切面异常：{}", e);
        }
    }


    /**
     * 参数拼装
     */
    private String argsArrayToString(Object[] paramsArray) {
        String params = "";
        if (paramsArray != null && paramsArray.length > 0) {
            for (Object o : paramsArray) {
                if (o != null) {
                    try {
                        Object jsonObj = JSON.toJSON(o);
                        params += jsonObj.toString() + " ";
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return params.trim();
    }
}
